package UILayer;//makes this class a part of the TUILayer package
import java.util.Scanner;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import CTRLayer.ProductCTR;//The TUILayer needs to know the ControlLayer
import ModelLayer.*;

/**
 * This class allows the user to interact with the IT-system. In this class
 * the user can create products and find products that already exists.
 * 
 * @author Gruppe 4 
 * @version 4. juni 2012
 */
public class ProductUI
{
    private ProductCTR productCTR;//reference to the ControlLayer
    private NonCompositeProduct nonCompositeProduct;

    /**
     * The constructor of the class initializes "ProductCTR", which is the class
     * that controls the product use case.
     */
    public ProductUI()
    {
        productCTR = new ProductCTR();
    }

    /**
     * This method starts the product menu.
     */
    public void start()
    {
        productCTR.testAddNonCompositeProduct();
        productMenu();
    }
   
    /**
     * This method calls a method according to what the user wishes.
     */
    private void productMenu()
    {
        boolean exit = false;
        while (!exit)
        {
            int choise = writeProductMenu();
            switch (choise)
            {
                case 1:
                    startGetProduct();
                    break;  
                case 2:
                    startAddProduct();
                    break;
                case 3:
                    startDeleteProduct();
                    break;
                case 4:
                    StartUpdateProductMenu();
                    break;
                case 5:
                    startListAllProducts();
                    break;
                case 6:
                    startUpdateQuantity();
                    break;
                case 7:
                    exit = true;
                    break;
            }
        }
    }
    
    /**
     * This method is the menu that the user sees when he/she enters the
     * part of the program that controls products.
     */
    private int writeProductMenu()
    {      // makes an object keyboard to read input from the screen
        Scanner keyboard = new Scanner(System.in);
        System.out.println("\f *** Product Menu ***");
        System.out.println(" (1) Find a product");
        System.out.println(" (2) Add product");
        System.out.println(" (3) Delete product");
        System.out.println(" (4) Update product");
        System.out.println(" (5) List all products");
        System.out.println(" (6) Update Quantities");
        System.out.println(" (7) Return");
        System.out.print("\n Make your choice: ");
        
        int choise = keyboard.nextInt();
        return choise;
    }
    
    /**
     * The method displays the Update Product Menu.
     */
    private void StartUpdateProductMenu()
    {      // makes an object keyboard to read input from the screen
        int barcode = inputBarcode();
        Product product = null;
        product = productCTR.findProduct(barcode);
        
        try {
            if (product != null) {
                printProductType(product);
                printProductGeneral(product);
                System.out.println("\n\n");
            } else {
                System.out.println("\n ** No product with that barcode was found! **");
                Thread.sleep(1500);
            }
        } catch (Exception e) {
            StartUpdateProductMenu();
        }
        
        Scanner keyboard = new Scanner(System.in);
        System.out.println("\f *** Update Product Menu ***");
        System.out.println(" (1) Update Product Name");
        System.out.println(" (2) Update Product Description");
        System.out.println(" (3) Update Price");
        System.out.println(" (4) Update Offer Price");
        System.out.println(" (5) Update Retail Price");
        System.out.print("\n Make your choice: ");
     
        int choice = keyboard.nextInt();
        makeUpdate(product, choice);
    }
    
    /**
     * The method controls update procedure.
     */
    private void makeUpdate(Product product, int choice)
    {
        Scanner keyboard = new Scanner(System.in);
        System.out.println("\n\nWrite new product data:  ");
        int newInt = 0;
        String newString = "";
        double newDouble = 0.0;
        try {
            newInt = keyboard.nextInt();
        } catch (Exception e) {
            try {
                newDouble = keyboard.nextDouble();
            } catch (Exception ex) {
                newString = keyboard.nextLine();
            }
        } 
        
        if (choice == 1) {
            product.setProductName(newString);
        } else if (choice == 2) {
            product.setProductDescription(newString);
        } else if (choice == 3) {
            product.setPrice(newDouble);
        } else if (choice == 4) {
            product.setOfferPrice(newDouble);
        } else if (choice == 5) {
            product.setRetailPrice(newDouble);
        } 
        
    }
    
    /**
     * The method takes the input of name of product.
     */
    private String inputProductName()
    {
         boolean ok = false;
         String productName = "";
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product name:  ");
                 productName = keyboard.nextLine();
                 ok = true;
             } catch (Exception e) { 
                 System.out.println("An error has occurred");
             }
         }
         
         return productName;
    }
    
    /**
     * The method takes the input of description.
     */
    private String inputProductDescription()
    {
         boolean ok = false;
         String productDescription = "";
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product Description:  ");
                 productDescription = keyboard.nextLine();
                 ok = true;
             } catch (Exception e) { 
                 System.out.println("An error has occurred");
             }
         }
         
         return productDescription;
    }
    
    /**
     * The method takes the input of barcode.
     */
    private int inputBarcode()
    {
         boolean ok = false;
         int barcode = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Barcode:  ");
                 barcode = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");    
             }
         }
         
         return barcode;
    }
    
    /**
     * The method takes the input of price.
     */
    private double inputPrice()
    {
         
         boolean ok = false;
         double price = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product Price:  ");
                 price = keyboard.nextDouble();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");  
             }
         }
         
         return price;
    }
    
    /**
     * The method takes the input of offer price.
     */
    private double inputOfferPrice()
    {
         boolean ok = false;
         double price = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write New Offer Price:  ");
                 price = keyboard.nextDouble();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");  
             }
         }
         
         return price;
    }
    
    /**
     * The method takes the input of retail price.
     */
    private double inputRetailPrice()
    {
         boolean ok = false;
         double retailPrice = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product Retail Price:  ");
                 retailPrice = keyboard.nextDouble();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");
             }
         }
         
         return retailPrice;
    }
    
    /**
     * The method takes the input of maximum capacity.
     */
    private int inputMaxCapacity()
    {
         boolean ok = false;
         int maxCapacity = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Max Capacity:  ");
                 maxCapacity = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");
             }
         }
         
         return maxCapacity;
    }
    
    /**
     * The method takes the input of minimum capacity.
     */
    private int inputMinCapacity()
    {
         boolean ok = false;
         int minCapacity = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Min Capacity:  ");
                 minCapacity = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");
             }
         }
         
         return minCapacity;
    }
    
    /**
     * The method takes the input of location.
     */
    private String inputLocation()
    {
         boolean ok = false;
         String location = "";
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product Location:  ");
                 location = keyboard.nextLine();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("An error has occurred");
             }
                 
         }
         return location;
    }
    
    /**
     * The method takes the input of quantity.
     */
    private int inputQuantity()
    {
         boolean ok = false;
         int quantity = 0;
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write quantity:  ");
                 quantity = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.print("Only numbers allowed, try again.");
             }
            
         }
         return quantity;
    }
    
    /**
     * The method takes the input of serialnumber.
     */
    private String inputSerialNumber()
    {
         boolean ok = false;
         String serialNumber = "";
         
         while (!ok) {
             try {
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Serial Number:  ");
                 serialNumber = keyboard.nextLine();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("An error has occurred");
             }
                
         }
         return serialNumber;
    }
    // end input methods
    
    /**
     * The method starts the add Product procedure.
     */
    private void startAddProduct()
    {
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" (1) Add Non Composite Product");
        System.out.println(" (2) Add Composite Product");
        int choise = keyboard.nextInt();
        
        if (choise == 1) {
            addNonCompositeProduct();
        } else if (choise == 2) {
            addCompositeProduct();
        }
    }
    
    /**
     * The method adds a NonCompositeProduct to OrderCollection orders.
     */
    private void addNonCompositeProduct()
    {
        String productName = inputProductName();
        String productDescription = inputProductDescription();
        int barcode = inputBarcode();
        double price = inputPrice();
        double retailPrice = inputRetailPrice();
        int maxCapacity = inputMaxCapacity();
        int minCapacity = inputMinCapacity();
        String location = inputLocation();
        int quantity = inputQuantity();

        productCTR.addNonCompositeProduct(productName, productDescription, barcode, price, retailPrice, 
                              maxCapacity, minCapacity, location, quantity);
        
        System.out.println("");
        System.out.println("");  
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" (1) Add Serial Numbers");
        System.out.println(" (2) Finish");
        int choise = keyboard.nextInt();
                              
        if (choise == 1) {
            addProductItem(barcode, quantity);
        }
    }
    
    /**
     * The method adds a ProductItem to a Product.
     */
    private void addProductItem(int barcode, int quantity) 
    {
        int index = 0;
        while (index < quantity) {
            String serialNumber = inputSerialNumber();
            productCTR.createProductItem(barcode, serialNumber);
            index++;
        }
    }
    
    /**
     * The method adds a CompositeProduct to PartList.
     */
    private void addCompositeProduct()
    {
        String productName = inputProductName();
        String productDescription = inputProductDescription();
        int barcode = inputBarcode();
        double price = inputPrice();
        double retailPrice = inputRetailPrice();
        int quantity = inputQuantity();

        productCTR.createCompositeProduct(productName, productDescription, barcode, 
                                       price, retailPrice, quantity);
                                       
        addSubProducts(barcode, 1);                               
        
        System.out.println("");
        System.out.println("");  
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" (1) Add Serial Numbers");
        System.out.println(" (2) Finish");
        int choise = keyboard.nextInt();
                              
        if (choise == 1) {
            addProductItem(barcode, quantity);
        }
    }
    
    /**
     * The method adds subProducts to PartList.
     */
    private void addSubProducts(int barcode, int callAgain) {
        System.out.println("");
        System.out.println("");  
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" Tilføj underprodukter:");
        System.out.println(" (1) Add new subproduct");
        System.out.println(" (2) Finish");
        callAgain = keyboard.nextInt();
        
        if(callAgain == 1) {
            int subBarcode = inputBarcode();
            int quanitity = inputQuantity();
            productCTR.addPartlist(barcode, subBarcode, quanitity);
            addSubProducts(barcode, callAgain);
        }
    }
    
    /**
     * The method finds a product from barcode.
     */
    private void startGetProduct()
    {
        int barcode = inputBarcode();
        
        Product product = null;
        product = productCTR.findProduct(barcode);
        
        try {
            if (product != null) {
                System.out.println("");
                System.out.println("");
                System.out.println("");
                
                printProductType(product);
                printProductGeneral(product);
                
                System.out.println("\n Press the enter key to return to menu");
                Scanner sc = new Scanner(System.in);
                while(!sc.nextLine().equals(""));
                
            } else {
                
                System.out.println("\n ** No product with that barcode was found! **");
                Thread.sleep(1500);
                
            }
        }
        catch (Exception e)  {
            System.out.println(" ** An error has occurred! **");
        }
        
    }
    
    /**
     * The method deletes a product from barcode.
     */
    private void startDeleteProduct() 
    {
        int barcode = inputBarcode();
        
        try {
            if(productCTR.deleteProduct(barcode)) {
                System.out.println("\n **Product deleted! **");
                Thread.sleep(1500);
            }
            else {
                System.out.println("\n ** No product with that barcode was found! **");
                Thread.sleep(1500);
            }
        }
        catch (Exception e)  {
            System.out.println(" ** An error has occurred! **");
        }
    }
  
    /**
     * The method lists all products.
     */
    private void startListAllProducts() 
    {
        HashMap<Integer, Product> productList = productCTR.listAllProducts();
     
        System.out.println("");
        
        Collection c = productList.values();
        Iterator itr = c.iterator();

        while(itr.hasNext()) {
            Product product = (Product) itr.next();
            printProductType(product);
            printProductGeneral(product);
        }
        
        Scanner sc = new Scanner(System.in);
        while(!sc.nextLine().equals(""));
    }
    
    /**
     * This method starts the update the quantity procedure of a product.
     */
    private void startUpdateQuantity() 
    {
        HashMap<Integer, Product> productList = productCTR.listAllProducts();
        System.out.println('\f');
        System.out.println("");
        
        Collection c = productList.values();
        Iterator itrc = c.iterator();
        int index = 0;

        while(itrc.hasNext()) {
            Product product = (Product) itrc.next();
            
            if (product instanceof NonCompositeProduct) {
                int barc = product.getBarcode();
                            
                //quan
                int quan = product.getQuantity();
                            
                //max handle
                NonCompositeProduct nonCompositeProduct = (NonCompositeProduct) product;
                int max = nonCompositeProduct.getMaxCapacity();
                // Customer customer = (Customer) person;
                
                //min handle
                int min = nonCompositeProduct.getMinCapacity();
                
                //diff handle
                int diff = min - quan;
                if (quan < min) {
                    index++;
                    System.out.println("");
                    System.out.println("--- NEW PRODUCT ---");
                    System.out.println("Product Name: " + product.getProductName());
                    
                    System.out.println("Barcode is: " + barc);
                    System.out.println("Quantity is: " + quan);
                    System.out.println("Max Capacity is: " + max);
                    System.out.println("Min Capacity is: " + min);
                    
                    System.out.println(" *** Warning! This Product has Exceeded minimum Quantity ***");
                    System.out.println("                       - and By " + diff + " units. -");
                }
                System.out.println("");
            }
        }
        
        if (index == 0) {
            System.out.print("None quantities are lower than minimum.");
            System.out.println("\n\n Press the enter key to return to menu");
            Scanner sc = new Scanner(System.in);
            while(!sc.nextLine().equals(""));
        } else {
            updateQuantity();
        }
        
    }
        
    /**
     * This method updates the quantity of a product.
     */
    private void updateQuantity()
    {
        int barcode = inputBarcode();
        Product product = productCTR.findProduct(barcode);
        int newQuantity = inputQuantity();
        product.addToQuantity(newQuantity);
        System.out.println(" Product Quantity Updated to - " + product.getQuantity() + " units");
        
        System.out.println("");
        System.out.println("");  
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" (1) Add Serial Numbers");
        System.out.println(" (2) Finish");
        int choice = keyboard.nextInt();
                              
        if (choice == 1) {
            addProductItem(barcode, newQuantity);
        }
        
        Scanner keyboard2 = new Scanner(System.in);
        System.out.println(" (1) Back to list of products that needs to be updated.");
        System.out.println(" (2) Finish");
        int choice2 = keyboard2.nextInt();
        
        if (choice2 == 1) {
            startUpdateQuantity();
        }
    }
   
    // Printing for products
    /**
     * This method determines the instance of an object and depending on its instance type prints information about the type it is of.
     */
    private void printProductType(Product product)
    {
        if (product instanceof NonCompositeProduct) {
            NonCompositeProduct newProduct = (NonCompositeProduct) product;
            System.out.println(" -- Non Composite Product Information --");
            System.out.println("Max capacity: " + newProduct.getMaxCapacity());
            System.out.println("Min capacity: " + newProduct.getMinCapacity());
            System.out.println("Location: " + newProduct.getLocation());
        } else if (product instanceof CompositeProduct) {
            CompositeProduct newProduct = (CompositeProduct) product;
            System.out.println(" -- Composite Product Information --");
            for (Partlist child : newProduct.getChildren()) {
                 Product subProduct = child.getProduct();
                 printProductGeneral(subProduct);
            }    
        }
        System.out.println("");
    }
    
    /**
     * This method prints general product information.
     */
    private void printProductGeneral(Product product) {
        System.out.println("Product name: " + product.getProductName());
        System.out.println("Product description: " + product.getProductDescription());
        System.out.println("Barcode: " + product.getBarcode());
        System.out.println("Price: " + product.getPrice());
        System.out.println("Retail price: " + product.getRetailPrice());
        System.out.println("Quantity: " + product.getQuantity());
        if (product.getOfferPrice()==0.0) {
            System.out.println("Offer price: [not set]");
        } else {
            System.out.println("Offer price: " + product.getOfferPrice());
        }
        System.out.println("");
    }
}